home *** CD-ROM | disk | FTP | other *** search
- /* National Institute of Standards and Technology (NIST)
- /* National Computer System Laboratory (NCSL)
- /* Office Systems Engineering (OSE) Group
- /* ********************************************************************
- /* D I S C L A I M E R
- /* (March 8, 1989)
- /*
- /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
- /* NCSL OSE SGML parser validation suite. If the SGML parser and/or
- /* validation suite is modified by someone else and passed on, NIST wants
- /* the parser's recipients to know that what they have is not what NIST
- /* distributed, so that any problems introduced by others will not
- /* reflect on our reputation.
- /*
- /* Policies
- /*
- /* 1. Anyone may copy and distribute verbatim copies of the SGML source
- /* code as received in any medium.
- /*
- /* 2. Anyone may modify your copy or copies of SGML parser source code or
- /* any portion of it, and copy and distribute such modifications provided
- /* that all modifications are clearly associated with the entity that
- /* performs the modifications.
- /*
- /* NO WARRANTY
- /* ===========
- /*
- /* NIST PROVIDES ABSOLUTELY NO WARRANTY. THE SGML PARSER AND VALIDATION
- /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
- /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
- /* WITH YOU. SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
- /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
- /*
- /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
- /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
- /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
- /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
- /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
- /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
- /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
- */
-
- /************************************************************************/
- /* TITLE: SGML PARSER */
- /* SYSTEM: DOCUMENT PROCESSOR */
- /* SUBSYSTEM: */
- /* SOURCE FILE: DIUTIL.C */
- /* AUTHOR: Steven Lindeman, Fred Maples */
- /* */
- /* DATE CREATED: */
- /* LAST MODIFIED: */
- /* */
- /* REVISIONS */
- /* WHEN WHO WHY */
- /************************************************************************/
- #include <stdio.h>
- #include <ctype.h>
- #include "didefs.h"
- #include "diglobal.h"
-
- /*----------------------------------------------*/
- /* A D A L L O C */
- /* Allocates enough memory for one attri- */
- /* bute description linked list entry. */
- /*----------------------------------------------*/
- ATTRDESC *adalloc()
- {
- /* char *calloc();*/
- ATTRDESC *retptr;
- if ((retptr=(ATTRPTR) malloc(sizeof(ATTRDESC))) == NULL)
- ourexit(2,"\nInsufficient memory in parse3.\n");
- return(retptr);
- }
-
- /*----------------------------------------------*/
- /* O Q A L L O C */
- /*----------------------------------------------*/
- OUT_QUEUE *oqalloc()
- {
- /* char *calloc();*/
- OUT_QUEUE *retptr;
- if ((retptr=(OUT_QUEUE_PTR) malloc(sizeof(OUT_QUEUE))) == NULL)
- ourexit(2,"\nInsufficient memory in parse3.\n");
- return(retptr);
- }
-
- /*------------------------------------------------------*/
- /* C H E C K _ C R */
- /* This routine dumps out the carriage returns */
- /* that were previously saved. At this point we */
- /* know they are significant. */
- /*------------------------------------------------------*/
- void check_cr(num_cr,cr_found,first_time,end_of_elt)
- unsigned *num_cr;
- BOOLEAN cr_found,*first_time,end_of_elt;
- {
- if (*first_time) {
- (*put_ctr)('\n',ctrfp);
- *first_time = FALSE;
- }
- if (cr_found) {
- (*print_ctr)(ctrfp,"|");
- while((*num_cr)-->0)
- (*print_ctr)(ctrfp,"\n[]");
- if (!end_of_elt)
- (*put_ctr)('\n',ctrfp);
- }
- return;
- }
-
- /*--------------------------------------------------------------*/
- /* C H E C K _ E N T I T Y */
- /* This routine is called when a general entity reference */
- /* has occurred either in the data stream or from an */
- /* attribute value literal. */
- /*--------------------------------------------------------------*/
- void check_entity(cdata_attr,num_csdata,entptr,datatext_read,entname,actual_length,inside_attr,inchar)
- BOOLEAN cdata_attr;
- unsigned *num_csdata;
- ENTITYDESC *entptr;
- BOOLEAN *datatext_read;
- char entname[];
- int *actual_length;
- BOOLEAN inside_attr;
- int *inchar;
- {
- char str_to_unget[LITLEN+6];
-
- entstack[entitylevel] = lookstack();
- if (++entitylevel > ENTLVL)
- ourexit(2,"\nError: Nesting level of entities > ENTLVL\n");
- switch(entptr->entitytype) {
- case KW_MS:
- sprintf(str_to_unget,"<![%s]]>",entptr->entityvalue);
- break;
- case KW_STARTTAG:
- sprintf(str_to_unget,"<%s>",entptr->entityvalue);
- break;
- case KW_ENDTAG:
- sprintf(str_to_unget,"</%s>",entptr->entityvalue);
- break;
- case KW_MD:
- sprintf(str_to_unget,"<!%s>",entptr->entityvalue);
- break;
- case KW_PI:
- if (inside_attr)
- ourexit(2,"\nError: Processing instruction invalid in attribute value literal.\n");
- else {
- (*print_ctr)(ctrfp,"\n[?%s]",entptr->entityvalue);
- (*applic)(PROC_INST,entptr->entityvalue);
- }
- break;
- case KW_CDATA:
- case KW_SDATA:
- if (inside_attr && !cdata_attr)
- ourexit(2,"\nError: CDATA or SDATA entity invalid in this attribute literal.\n");
- strcpy(str_to_unget,entptr->entityvalue);
- *datatext_read = TRUE;
- if (inside_attr)
- *num_csdata += 1; /* count of CDATA or SDATA references */
- break;
- case KW_SYSTEM:
- case KW_PUBLIC:
- (*print_ctr)(ctrfp,"\n[&%s]",entname);
- /* if ((fpstack[++fpindx]=fopen("fred","rb")) == NULL)
- ourexit(2,"Error: Unknown system entity reference.\n");
- */
- break;
- default:
- strcpy(str_to_unget,entptr->entityvalue);
- break;
- }
- if ((*inchar=our_fgetc(indoc)) != REFC)
- if (*inchar == RE) { /* RS and RE are insignificant */
- *inchar = our_fgetc(indoc); /* get RS */
- if (inside_attr)
- *actual_length += 2;
- }
- else
- our_ungetc(*inchar,indoc);
- unget_entity(str_to_unget);
- return;
- }
-
- /*------------------------------------------------------*/
- /* C H E C K _ F I X E D */
- /* This routine guarantees that the attribute */
- /* declared as being FIXED matches the actual */
- /* value that was given. If the two do not match */
- /* exactly, an error condition is raised. */
- /*------------------------------------------------------*/
- void check_fixed(defcode,str1,str2,length)
- ADFLT defcode;
- char str1[],str2[];
- int length;
- {
- if (defcode==A_FIXED && strncmp(str1,str2,length)!=0) {
- sprintf(error_msg,"%s'%s'.\n","\nError: FIXED attribute declared. Must use ",str2);
- FATAL_ERROR()
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* C R E A T E C M */
- /* */
- /* Called by :PUSHCREATE */
- /* */
- /* Returns :pointer to the new */
- /* content model */
- /* */
- /* Creates a copy of the given content model */
- /*------------------------------------------------------*/
- TNODE *createcm(oldptr)
- TNODE *oldptr;
- {
- TNODE *newptr,*newp,*oldp;
-
- if (oldptr != NULL) {
- newptr = talloc(); /* allocate a node */
- newptr->nodeid = oldptr->nodeid; /* copy nodeid to new node */
- newptr->occurind = newptr->copyoi = oldptr->occurind;
- newptr->contreq = newptr->copycontreq = oldptr->contreq;
- newptr->contref_attr = oldptr->contref_attr;
-
- /* ANDs are treated seperately, must build circular linked list
- instead of a binary tree. each element in list is an element
- of the AND group */
- if (oldptr->nodeid == AND) {
- newp = newptr->u.llptr = createcm(oldptr->u.llptr);
- oldp = oldptr->u.llptr;
- while(oldp->next != oldptr->u.llptr) {
- newp->next = createcm(oldp->next);
- oldp = oldp->next;
- newp = newp->next; /* move across both lists */
- }
- newp->next = newptr->u.llptr; /* finish off circular list */
- }
- else {
- newptr->left = createcm(oldptr->left); /* create new left pointer */
- newptr->u.right = createcm(oldptr->u.right); /* create new right ptr */
- }
- return(newptr);
- }
- return(NULL);
- }
-
- /*------------------------------------------------------*/
- /* C O M P A R E */
- /* */
- /* Called by :QSORT, BSEARCH */
- /* */
- /* Returns :TRUE, FALSE */
- /* */
- /* String compare to determine if two */
- /* strings are equal. */
- /*------------------------------------------------------*/
- compare(arg1,arg2)
- STENTRY *arg1,*arg2;
- {
- return(strcmp((char *)arg1,(char *)arg2));
- }
-
- /*------------------------------------------------------*/
- /* D E C R O I */
- /* This routine decrements the occurence indic- */
- /* ators. All that means is that an occurrence */
- /* of this model token has occurred. */
- /*------------------------------------------------------*/
- void decroi(ptr)
- TNODE *ptr;
- {
- switch(ptr->occurind) {
- case '+': /* one or more goes to zero or more */
- case '*': /* zero or more goes to zero or more */
- ptr->occurind = '*';
- break;
- #ifdef NEW
- case '*': /* zero or more goes to zero or more */
- #endif
- case '?': /* zero or one goes to none */
- case '1': /* one goes to none */
- ptr->occurind = '#';
- break;
- default:
- software_fault();
- }
- switch(ptr->contreq) {
- case C_FTOTSO:
- ptr->contreq = ptr->copycontreq = C_SOMETIMESO;
- break;
- case C_FTOWR:
- case C_FTO:
- ptr->contreq = C_NEVERO;
- break;
- case C_SOMETIMESO:
- case C_NEVERO:
- case C_ALWAYSO:
- break;
- default:
- software_fault();
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* D E L E T E _ F I L E S */
- /* Deletes temporary files built by DTD processor. */
- /* This routine is called only if the '-F' command */
- /* line option is left off. */
- /*------------------------------------------------------*/
- void delete_files(path)
- char path[];
- {
- char filename[PATHLEN];
-
- sprintf(filename,"%s%s",path,"dtdfile.sgm");
- unlink(filename);
- sprintf(filename,"%s%s",path,"attrfile.sgm");
- unlink(filename);
- sprintf(filename,"%s%s",path,"greffile.sgm");
- unlink(filename);
- sprintf(filename,"%s%s",path,"preffile.sgm");
- unlink(filename);
- sprintf(filename,"%s%s",path,"except.sgm");
- unlink(filename);
- return;
- }
-
- /*----------------------------------------------*/
- /* E X A L L O C */
- /* Allocates enough memory for one */
- /* exception linked list entry. */
- /*----------------------------------------------*/
- EXCEPTDESC *exalloc()
- {
- /* char *calloc(); */
- EXCEPTDESC *retptr;
- if ((retptr=(EXCEPTPTR) malloc(sizeof(EXCEPTDESC))) == NULL)
- ourexit(2,"\nInsufficient memory in parse3.\n");
- return(retptr);
- }
-
- /*------------------------------------------------------*/
- /* F L U S H _ B U F */
- /* This routine flushes the output buffer called */
- /* 'outbuf' to the output document called 'outdoc'. */
- /* Outbuf is assumed to not be null terminated, */
- /* so a null is placed at the end of the buffer */
- /* pointed to by bufptr. */
- /*------------------------------------------------------*/
- void flush_buf()
- {
- if (bufptr != 0) {
- outbuf[bufptr] = '\0'; /* bufptr always points to next entry place */
- (*print_ctr)(ctrfp,"%s",outbuf);
- bufptr = 0; /* points to end of buffer, nothing in buffer now */
- }
- empty_queue();
- return;
- }
-
- /*----------------------------------------------*/
- /* G E A L L O C */
- /* Allocates enough memory for one entity */
- /* description linked list entry. */
- /*----------------------------------------------*/
- ENTITYDESC *gealloc()
- {
- /* char *calloc(); */
- ENTITYDESC *retptr;
- if ((retptr=(ENTITYPTR) malloc(sizeof(ENTITYDESC))) == NULL)
- ourexit(2,"\nInsufficient memory in parse3.\n");
- return(retptr);
- }
-
- /*----------------------------------------------*/
- /* G R A L L O C */
- /* Allocates enough memory for one group */
- /* description linked list entry. */
- /*----------------------------------------------*/
- GROUPDESC *gralloc()
- {
- /* char *calloc(); */
- GROUPDESC *retptr;
- if ((retptr=(GROUPPTR) malloc(sizeof(GROUPDESC))) == NULL)
- ourexit(2,"\nInsufficient memory in parse3.\n");
- return(retptr);
- }
-
- /*----------------------------------------------*/
- /* I D _ I D R E F _ A L L O C */
- /* Allocates enough memory for one ID or */
- /* IDREF description linked list entry. */
- /*----------------------------------------------*/
- ID_IDREF_DESC *id_idref_alloc()
- {
- /* char *calloc(); */
- ID_IDREF_DESC *retptr;
- if ((retptr=(ID_IDREF_PTR) malloc(sizeof(ID_IDREF_DESC))) == NULL)
- ourexit(2,"\nInsufficient memory in parse3.\n");
- return(retptr);
- }
-
- /*------------------------------------------------------*/
- /* I N C R O I */
- /* Increments the occurence indicators. */
- /*------------------------------------------------------*/
- void incroi(ptr)
- TNODE *ptr;
- {
- switch(ptr->occurind) {
- case '*':
- ptr->occurind = '+'; /* zero or more goes to one or more */
- break;
- case '?':
- ptr->occurind = '1'; /* optional goes to required */
- break;
- default:
- software_fault();
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* I N P U T _ P S */
- /* This routine is used to input parameter */
- /* seperators that can be found in the front */
- /* part of marked sections. It gets as many */
- /* as possible and returns the number that it */
- /* found. */
- /*------------------------------------------------------*/
- inputps(penthead)
- ENTITYDESC *penthead;
- {
- int inchar;
- unsigned sepcount = 0;
-
- for(;;) {
- switch (inchar=our_fgetc(indoc)) {
- case RS:
- case RE:
- case SPACE:
- sepcount++;
- break;
- case OUR_EE:
- sepcount++;
- entitylevel--;
- break;
- /* must check if parameter entity reference */
- case PERO:
- if ((inchar = our_fgetc(indoc)) == EOF)
- return(EOF);
- /* if it is a parameter entity reference ...*/
- if (isalpha(inchar)){
- our_ungetc(inchar, indoc);
- if (++entitylevel > ENTLVL)
- ourexit(2,"\nError: Number of open entities > ENTLVL\n");
- reslvpref(penthead);
- sepcount++;
- break;
- }
- else {
- our_ungetc(inchar, indoc);
- our_ungetc(PERO, indoc);
- return(sepcount);
- }
- case '-':
- if ((inchar = our_fgetc(indoc)) == EOF)
- return(EOF);
- if (inchar == '-') {
- inpcomment();
- sepcount++;
- break;
- }
- our_ungetc(inchar, indoc);
- our_ungetc('-', indoc);
- return(sepcount);
- default:
- our_ungetc(inchar, indoc);
- return(sepcount);
- }
- }
- }
-
- /*------------------------------------------------------*/
- /* I N P C O M M E N T */
- /* This routine inputs a comment from indoc. */
- /*------------------------------------------------------*/
- void inpcomment()
- {
- int inchar;
- for(;;) {
- if ((inchar=our_fgetc(indoc)) == EOF)
- ourexit(2,"\nError: EOF found while processing comment");
- if (inchar != '-')
- continue;
- if ((inchar=our_fgetc(indoc)) == EOF)
- ourexit(2,"\nError: EOF found while processing comment");
- if (inchar == '-')
- return;
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* I S A L L O C */
- /* This routine allocates enough memory for one */
- /* input stack entry. */
- /*------------------------------------------------------*/
- INPUT_STACK *isalloc()
- {
- /* char *calloc(); */
- INPUT_STACK *retptr;
- if ((retptr=(INPUT_STACK_PTR) malloc(sizeof(INPUT_STACK))) == NULL)
- ourexit(2,"\nInsufficient memory in parse3.\n");
- return(retptr);
- }
-
- /*------------------------------------------------------*/
- /* L I N S R C H */
- /* This routine performs a search on the symbol */
- /* table for the address of the record correspond- */
- /* ing to the token passed to it. If there is */
- /* not an entry in the symbol table for that */
- /* token, a NULL ptr is returned. */
- /*------------------------------------------------------*/
- STENTRY *linsrch(symtable,token,numsym)
- STENTRY symtable[];
- int token,numsym;
- {
- int thissym;
-
- thissym = 0;
- while(thissym!=numsym && symtable[thissym].tokenid!=token)
- thissym++;
- return(thissym < numsym ? &(symtable[thissym]) : NULL);
- }
-
- /*------------------------------------------------------*/
- /* O U R E X I T */
- /* */
- /* Called by: everybody */
- /* */
- /* Returns: doesn't */
- /* */
- /* This routine prints an explanatory error */
- /* message and then terminates program execution. */
- /*------------------------------------------------------*/
- void ourexit(errcode,msg)
- int errcode;
- char *msg;
- {
- static int error_count=0;
-
- fprintf(stdout,"%s\n",msg);
- switch(errcode) {
- case 0:
- break;
- default:
- exit(99);
- }
- if (error_count++ > MAX_ERRORS)
- exit(99);
- }
-
- /*------------------------------------------------------*/
- /* P L A C E _ I N _ Q U E U E */
- /*------------------------------------------------------*/
- void place_in_queue(thiscode,thisstr1,thisstr2)
- int thiscode;
- char *thisstr1,*thisstr2;
- {
- OUT_QUEUE *ptr,*curr;
-
- ptr = oqalloc();
- ptr->code = thiscode;
- strcpy(ptr->str1,thisstr1);
- strcpy(ptr->str2,thisstr2);
- ptr->next = NULL;
- if (head == NULL)
- head = ptr;
- else {
- for (curr=head; curr->next!=NULL; curr=curr->next);
- curr->next = ptr;
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* E M P T Y _ Q U E U E */
- /*------------------------------------------------------*/
- void empty_queue()
- {
- OUT_QUEUE *curr,*temp;
- for (curr=head; curr!=NULL; temp=curr, curr=curr->next, free((char *)temp)) {
- switch(curr->code) {
- case TAG_NAME:
- (*applic)(TAG_NAME,curr->str1,"");
- break;
- case TAG_ATTR:
- (*applic)(TAG_ATTR,curr->str1,curr->str2);
- break;
- case TAG_END:
- (*applic)(TAG_END,"","");
- break;
- case DATA_STG:
- (*applic)(DATA_STG,curr->str1,"");
- break;
- case PROC_INST:
- (*applic)(PROC_INST,curr->str1,"");
- break;
- case END_TAG_NAME:
- (*applic)(END_TAG_NAME,curr->str1,"");
- break;
- }
- }
- head = NULL;
- return;
- }
-
- /*------------------------------------------------------*/
- /* C L E A R _ Q U E U E */
- /*------------------------------------------------------*/
- void clear_queue()
- {
- OUT_QUEUE *curr,*temp;
- for (curr=head; curr!=NULL; temp=curr, curr=curr->next, free((char *)temp));
- head = NULL;
- return;
- }
-
- /*------------------------------------------------------*/
- /* P U S H */
- /* */
- /* Called by :PUSHCREATE, LOOKSTACK */
- /* */
- /* Returns :VOID */
- /* */
- /* Pushes a symbol table entry */
- /* pointer onto a push-down stack. */
- /*------------------------------------------------------*/
- void push(ptr)
- STENTRY *ptr;
- {
- if (sp < TAGLVL)
- stack[sp++]=ptr; /* push ptr on stack */
- else /* stack exceeds TAGLVL (24) */
- ourexit(2,"\nError: Number of open elements > TAGLVL.\n");
- return;
- }
-
- /*------------------------------------------------------*/
- /* P O P */
- /* Called by :POPFREE, LOOKSTACK */
- /* Returns :pointer to symbol table entry */
- /* */
- /* Pops a symbol table entry pointer */
- /* off of a push-down stack */
- /*------------------------------------------------------*/
- STENTRY *pop()
- {
- if (sp > 0)
- return(stack[--sp]); /* pop ptr off stack */
- else
- return(NULL);
- }
-
- /*------------------------------------------------------*/
- /* P O P F R E E */
- /* This routine pops a ptr from content model ptr */
- /* stack and deletes corresponding content model. */
- /*------------------------------------------------------*/
- STENTRY *popfree(ptr)
- TNODE *ptr;
- {
- STENTRY *retptr;
- EXCEPTDESC *p;
-
- retptr = pop();
- retptr->num_open--;
-
- if (currexcl!=NULL && retptr->miniexcept&EXCL_MASK && retptr->num_open==0) {
- if (currexcl == retptr->exclusion)
- currexcl = NULL;
- else {
- p = last_sublist(currexcl,retptr->exclusion); /* P can't be NULL */
- p->nextglobal = NULL;
- }
- retptr->miniexcept &= ~EXCL_MASK; /* disallow exclusions */
- }
-
- if (currincl!=NULL && retptr->miniexcept&INCL_MASK && retptr->num_open==0) {
- if (currincl == retptr->inclusion)
- currincl = NULL;
- else {
- p = last_sublist(currincl,retptr->inclusion); /* P can't be NULL */
- p->nextglobal = NULL;
- }
- retptr->miniexcept &= ~INCL_MASK; /* disallow inclusions */
- }
- delete(ptr);
- return(retptr);
- }
-
- /*------------------------------------------------------*/
- /* P U S H C R E A T E */
- /* */
- /* Returns: ptr to new content model */
- /* */
- /* pushes ptr on stack and creates a */
- /* content model from the virgin copy */
- /*------------------------------------------------------*/
- TNODE *pushcreate(tp)
- STENTRY *tp;
- {
- EXCEPTDESC *p;
-
- tp->num_open++; /* number of currently open elements for this one */
-
- if (!(tp->miniexcept & EXCL_MASK))
- if ((p=last_global(currexcl)) == NULL)
- currexcl = tp->exclusion;
- else
- p->nextglobal = tp->exclusion;
- if (tp->exclusion != NULL)
- tp->miniexcept |= EXCL_MASK;
-
- if (!(tp->miniexcept & INCL_MASK))
- if ((p=last_global(currincl)) == NULL)
- currincl = tp->inclusion;
- else
- p->nextglobal = tp->inclusion;
- if (tp->inclusion != NULL)
- tp->miniexcept |= INCL_MASK;
-
- if (find_except(currexcl,tp->tokenid) == TRUE) {
- sprintf(error_msg,"\n%s%s%s\n","Error: Invalid tokenid, ",tp->nametoken," is excluded.");
- FATAL_ERROR()
- }
- push(tp);
- return(createcm(tp->cmptr));
- }
-
- /*------------------------------------------------------*/
- /* P U T C H A R _ O U T B U F */
- /* Puts a character into the output buffer. */
- /*------------------------------------------------------*/
- void putchar_outbuf(inchar)
- int inchar;
- {
- outbuf[bufptr++] = inchar;
- if (bufptr >= TAGLEN+200)
- flush_buf();
- return;
- }
-
- /*------------------------------------------------------*/
- /* P U T S T R _ O U T B U F */
- /* Puts a character string into the output buffer */
- /*------------------------------------------------------*/
- void putstr_outbuf(string)
- char string[];
- {
- if (bufptr+strlen(string) >= TAGLEN+200)
- flush_buf();
- if (strlen(string) >= TAGLEN+200)
- (*print_ctr)(ctrfp,"%s",string);
- outbuf[bufptr] = '\0';
- strcat(outbuf,string);
- bufptr += strlen(string); /* don't need the null string yet */
- return;
- }
-
- /*------------------------------------------------------*/
- /* R E D U C E O I */
- /* This routine reduces the occurence indicators. */
- /* This is done in the initilization part to make */
- /* sub-models optional if their parent nodes are */
- /* optional. */
- /*------------------------------------------------------*/
- void reduceoi(ptr)
- TNODE *ptr;
- {
- switch(ptr->occurind) {
- case '+':
- ptr->copyoi = ptr->occurind = '*';
- break;
- case '1':
- ptr->copyoi = ptr->occurind = '?';
- break;
- default:
- software_fault();
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* R E S T O R E O I */
- /* This routine restores the occurance indicators */
- /* of the whole tree to their original values */
- /*------------------------------------------------------*/
- void restoreoi(ptr)
- TNODE *ptr;
- {
- TNODE *currp;
-
- if (ptr != NULL) {
- if (ptr->nodeid == AND) {
- currp = ptr->u.llptr;
- while(currp->next != ptr->u.llptr) { /* restore each one in list */
- restoreoi(currp);
- currp = currp->next;
- }
- restoreoi(currp); /* don't forget to restore last one */
- }
- else {
- restoreoi(ptr->left); /* restore left subtree */
- restoreoi(ptr->u.right); /* restore right subtree */
- }
- ptr->occurind = ptr->copyoi; /* restores oi from unused copy */
- switch(ptr->contreq) {
- case C_NEVERO:
- if (ptr->copycontreq != C_FTO)
- ptr->contreq = ptr->copycontreq;
- break;
- case C_SOMETIMESO:
- if (ptr->copycontreq != C_FTOTSO)
- ptr->contreq = ptr->copycontreq;
- break;
- default:
- ptr->contreq = ptr->copycontreq;
- break;
- }
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* R E Q _ N O T _ P R O C */
- /* Traverses through the attribute list to decide */
- /* if any attributes were REQUIRED but not pro- *
- /* cessed. FALSE is returned if none were found */
- /* and TRUE is returned if at least one was found. */
- /*------------------------------------------------------*/
- req_not_proc(thisadp)
- ATTRDESC *thisadp;
- {
- BOOLEAN retval;
- retval = FALSE;
- while(retval==FALSE && thisadp!=NULL)
- if ((thisadp->processed==FALSE) && ((thisadp->defcode==A_REQD) ||
- (thisadp->defcode==A_CURRENT && thisadp->u2.currgrp==NULL)))
- retval = TRUE;
- else
- thisadp = thisadp->next;
- return(retval);
- }
-
- /*------------------------------------------------------*/
- /* R E S L V P R E F */
- /* This routine resolves any parameter entity refer- */
- /* ences at a separator level. It inputs the entity */
- /* name, searches a table on the name getting its */
- /* entity text, and 'ungets' the text for further */
- /* processing. */
- /*------------------------------------------------------*/
- void reslvpref(penthead)
- ENTITYDESC *penthead;
- {
- char namearray[NAMELEN+1];
- char tarray[LITLEN+6];
- int inchar;
- ENTITYDESC *entptr;
-
- /* input the parameter entity name */
- if (get_entname(namearray,nullfnc) < NAMELEN-1) {
-
- if ((entptr=find_entity(penthead,namearray,FALSE)) == NULL) {
- sprintf(error_msg,"\n%s'%s'.\n","Error: Unknown parameter entity reference ",namearray);
- FATAL_ERROR()
- }
- switch(entptr->entitytype){
- case KW_MD:
- sprintf(tarray,"%s%s%s","<!",entptr->entityvalue,">");
- if ((inchar=our_fgetc(indoc)) != EOF)
- ourexit(2,"\nError: EOF found while resolving parameter entity reference.\n");
- if (inchar != REFC)
- if (inchar == RE) /* RS and RE are insignificant */
- inchar = our_fgetc(indoc); /* get RS */
- else
- our_ungetc(inchar, indoc);
- unget_entity(tarray);
- break;
- case KW_ENDTAG:
- sprintf(tarray,"%s%s%s","</",entptr->entityvalue,">");
- if ((inchar=our_fgetc(indoc)) != EOF)
- ourexit(2,"\nError: EOF found while resolving parameter entity reference.\n");
- if (inchar != REFC)
- if (inchar == RE) /* RS and RE are insignificant */
- inchar = our_fgetc(indoc); /* get RS */
- else
- our_ungetc(inchar, indoc);
- unget_entity(tarray);
- break;
- case KW_STARTTAG:
- sprintf(tarray,"%s%s%s","<",entptr->entityvalue,">");
- if ((inchar=our_fgetc(indoc)) != EOF)
- ourexit(2,"\nError: EOF found while resolving parameter entity reference.\n");
- if (inchar != REFC)
- if (inchar == RE) /* RS and RE are insignificant */
- inchar = our_fgetc(indoc); /* get RS */
- else
- our_ungetc(inchar, indoc);
- unget_entity(tarray);
- break;
- case KW_MS:
- sprintf(tarray,"%s%s%s","<![",entptr->entityvalue,"]]>");
- if ((inchar=our_fgetc(indoc)) == EOF)
- ourexit(2,"\nError: EOF found while resolving parameter entity reference.\n");
- if (inchar != REFC)
- if (inchar == RE) /* RS and RE are insignificant */
- inchar = our_fgetc(indoc); /* get RS */
- else
- our_ungetc(inchar, indoc);
- unget_entity(tarray);
- break;
- case NULL:
- if ((inchar=our_fgetc(indoc)) == EOF)
- ourexit(2,"\nError: EOF found while resolving parameter entity reference");
- if (inchar != REFC)
- if (inchar == RE) /* RS and RE are insignificant */
- inchar = our_fgetc(indoc); /* get RS */
- else
- our_ungetc(inchar, indoc);
- /* unget parameter literal */
- unget_entity(entptr->entityvalue);
- break;
- /* any other syntactic literal is illegal */
- default:
- ourexit(2,"\nError: Illegal use of syntactic literal in a PS entity reference.\n");
- break;
- }
- }
- else
- ourexit(2,"\nError: Reference name not found in PS entity reference.\n");
- return;
- }
-
- /*------------------------------------------------------*/
- /* S A V E _ C R S */
- /* During the processing of data, carriage returns */
- /* are read and saved. They may be output later */
- /* if it is found that are significant. */
- /*------------------------------------------------------*/
- BOOLEAN save_crs(num_cr,inchar)
- unsigned *num_cr;
- int *inchar;
- {
- BOOLEAN cr_found;
- for (cr_found = FALSE; *inchar == RE; (*num_cr)++) {
- cr_found = TRUE;
- if ((*inchar=our_fgetc(indoc)) == RS) /* should be a RS */
- *inchar = our_fgetc(indoc);
- }
- return(cr_found);
- }
-
- /*------------------------------------------------------*/
- /* S O F T W A R E _ F A U L T */
- /* This routine should NEVER be called. If it */
- /* is called, the parser has taken an unpredicted */
- /* path of execution and the program is halted. */
- /*------------------------------------------------------*/
- void software_fault()
- {
- fprintf(stderr,"Internal parser error. Contact Jim Heath of NBS @ (301) 975-3350.\n");
- exit(99);
- }
-
- /*----------------------------------------------*/
- /* T A L L O C */
- /* */
- /* Called by :BUILDTREE */
- /* */
- /* Returns :ptr to allocated node */
- /* */
- /* Allocates memory for one tree node. */
- /*----------------------------------------------*/
- TNODE *talloc()
- {
- /* char *calloc(); */
- TNODE *retptr;
- if ((retptr=(TPTR) malloc(sizeof(TNODE))) == NULL)
- ourexit(2,"\nInsufficient memory in parse3.\n");
- return(retptr);
- }
-
- /*------------------------------------------------------*/
- /* T E S T O I */
- /* This routine tests to see if occurance indicator */
- /* is mandatory or optional. */
- /*------------------------------------------------------*/
- OCCURIND testoi(ptr)
- TNODE *ptr;
- {
- OCCURIND retval;
-
- switch(ptr->occurind) {
- case '1': /* occurind is one */
- retval = ONE;
- break;
- case '+': /* occurind is one or more */
- retval = PLUS;
- break;
- case '?': /* occurind is zero or one */
- case '*': /* occurind is zero or more */
- retval = OPT;
- break;
- case '#': /* occurind is none */
- retval = OI_IS_NULL;
- break;
- default:
- software_fault();
- }
- return(retval);
- }
-
- /*------------------------------------------------------*/
- /* U N G E T _ E N T I T Y */
- /* This routine simply 'ungets' the given entity */
- /* string onto the input stack. First the SGML */
- /* 'Ee' (Entity end) signal is pushed on the */
- /* stack, then the string is pushed in reverse */
- /* order by unget_string. */
- /*------------------------------------------------------*/
- void unget_entity(string)
- char string[];
- {
- our_ungetc(OUR_EE,indoc);
- unget_string(string);
- return;
- }
-
- /*------------------------------------------------------*/
- /* U N G E T _ S T R I N G */
- /* This routine simply 'ungets' the given string */
- /* onto the input stack. Remember that the */
- /* string must be processed in reverse order. */
- /*------------------------------------------------------*/
- void unget_string(string)
- char string[];
- {
- register int i;
- for (i=strlen(string)-1; i>=0; i--)
- our_ungetc(string[i],indoc);
- return;
- }
-
- /*------------------------------------------------------*/
- /* U N G E T T O K E N */
- /* Places the given token (tag) back onto the */
- /* input stream. */
- /*------------------------------------------------------*/
- void ungettoken(token,tp)
- int token;
- STENTRY *tp;
- {
- state = GETOLD; /* set state to read from input stream */
- holdtoken = token;
- holdtp = tp; /* get table location from hold area */
- return;
- }
-
- /*------------------------------------------------------*/
- /* U N P R O C E S S */
- /* Traverses through the attribute list and */
- /* turns off the flag describing whether this */
- /* name has been processed in this tag. */
- /*------------------------------------------------------*/
- void unprocess(thisadp)
- ATTRDESC *thisadp;
- {
- while(thisadp != NULL) {
- thisadp->processed = FALSE;
- thisadp = thisadp->next;
- }
- return;
- }
-
- /*--------------------------------------------------------------*/
- /* C H E C K _ F O R _ M D O */
- /* This routine is called when the "<!" has already */
- /* been read while processing PCDATA. */
- /*--------------------------------------------------------------*/
- STATUS check_for_mdo(more_subdata,num_cr,cr_found,pcdata_ft)
- BOOLEAN *more_subdata;
- unsigned *num_cr;
- BOOLEAN cr_found,*pcdata_ft;
- {
- int inchar;
- STATUS retval;
-
- if ((inchar=our_fgetc(indoc)) == '-')
- if ((inchar=our_fgetc(indoc)) == '-') {
- unget_string("<!--");
- *more_subdata = FALSE;
- }
- else {
- retval = FOUND;
- check_cr(num_cr,cr_found,pcdata_ft,FALSE);
- (*print_ctr)(ctrfp,"<!-");
- (*applic)(DATA_STG,"<!-","");
- our_ungetc(inchar,indoc);
- }
- else
- if (isalpha(inchar) || inchar=='[' || inchar==MARKUP_END) {
- our_ungetc(inchar,indoc);
- unget_string("<!");
- *more_subdata = FALSE;
- }
- else {
- retval = FOUND;
- check_cr(num_cr,cr_found,pcdata_ft,FALSE);
- (*print_ctr)(ctrfp,"<!");
- (*applic)(DATA_STG,"<!","");
- our_ungetc(inchar,indoc);
- }
- return(retval);
- }
-
- /*------------------------------------------------------*/
- /* C R O S S _ I D _ I D R E F */
- /* Performs a cross reference evaluation for IDs */
- /* and IDREFs to make sure there is an ID found */
- /* for every IDREF. There is no requirement that */
- /* states an IDREF must be found for every ID. */
- /*------------------------------------------------------*/
- ID_IDREF_DESC *cross_id_idref(idptr,idrefptr)
- ID_IDREF_DESC *idptr,*idrefptr;
- {
- while(idrefptr!=NULL && find_id(idptr,idrefptr->name)==TRUE)
- idrefptr = idrefptr->next;
- return(idrefptr);
- }
-
- /*------------------------------------------------------*/
- /* D E L E T E */
- /* */
- /* Called by :DELETE,POPFREE */
- /* */
- /* Returns :VOID */
- /* */
- /* Deletes the binary tree pointed to by ptr */
- /*------------------------------------------------------*/
- void delete(ptr)
- TNODE *ptr;
- {
- TNODE *currp,*futp;
- if (ptr != NULL) {
- if (ptr->nodeid == AND) {
- currp = ptr->u.llptr;
- while(currp->next != ptr->u.llptr) {
- futp = currp->next;
- /* must save a ptr to node to be processed next, futp,
- because will 'delete' ptr to it now */
- delete(currp);
- currp = futp;
- }
- delete(currp); /* don't forget last one in list */
- }
- else {
- delete(ptr->left); /* delete left subtree */
- delete(ptr->u.right); /* delete right subtree */
- free((char *)ptr); /* unallocate memory location */
- }
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* F I N D _ A T T R */
- /* Searches through the attribute list for the */
- /* given name and returns the pointer to list */
- /* entry if found, else returns NULL. */
- /*------------------------------------------------------*/
- ATTRDESC *find_attr(thisattr,thisadp)
- char thisattr[];
- ATTRDESC *thisadp;
- {
- while((thisadp!=NULL) && (strcmp(thisattr,thisadp->attrname)!=0))
- thisadp = thisadp->next;
- return(thisadp);
- }
-
- /*------------------------------------------------------*/
- /* F I N D _ G R O U P */
- /* Searches through the group list for the */
- /* given name and returns the pointer to list */
- /* entry if found, else returns NULL. */
- /*------------------------------------------------------*/
- GROUPDESC *find_group(thisgroup,thisgrp)
- char thisgroup[];
- GROUPDESC *thisgrp;
- {
- while((thisgrp!=NULL) && (strcmp(thisgroup,thisgrp->groupname)!=0))
- thisgrp = thisgrp->next;
- return(thisgrp);
- }
-
- /*------------------------------------------------------*/
- /* F I N D _ I D */
- /* Searches through the ID list for the given */
- /* name and returns the pointer to the list */
- /* entry if the name is found, else returns NULL. */
- /*------------------------------------------------------*/
- BOOLEAN find_id(idptr,thisname)
- ID_IDREF_DESC *idptr;
- char thisname[];
- {
- while(idptr!=NULL && strcmp(idptr->name,thisname)!=0)
- idptr = idptr->next;
- return(idptr!=NULL ? TRUE : FALSE);
- }
-
- /*------------------------------------------------------*/
- /* F I N D _ E N T I T Y */
- /* Searches through the ENTITY list for the given */
- /* name and returns the pointer to the list */
- /* entry if the name is found, else returns NULL. */
- /* If there is a #DEFAULT entry and a direct */
- /* match is not found, the ptr to the first */
- /* #DEFAULT entry is returned. */
- /*------------------------------------------------------*/
- ENTITYDESC *find_entity(entptr,thisname,look_for_default)
- ENTITYDESC *entptr;
- char thisname[];
- BOOLEAN look_for_default;
- {
- ENTITYDESC *first_def;
-
- first_def = NULL; /* points to first #DEFAULT entry in list */
- while(entptr!=NULL && strcmp(entptr->entityname,thisname)!=0) {
- if (first_def==NULL && look_for_default && strcmp(entptr->entityname,"#DEFAULT")==0)
- first_def = entptr;
- entptr = entptr->next;
- }
- return(entptr==NULL ? first_def : entptr);
- }
-
- /*------------------------------------------------------*/
- /* F I N D _ E X C E P T */
- /* This routine searches the exception list */
- /* (inclusion or exclusion) for the identifier */
- /* specified in the parameter list. */
- /*------------------------------------------------------*/
- BOOLEAN find_except(exptr,thisid)
- EXCEPTDESC *exptr;
- int thisid;
- {
- while(exptr!=NULL && exptr->tokenid!=thisid)
- exptr = exptr->nextglobal;
- return(exptr!=NULL ? TRUE : FALSE);
- }
-
- /*------------------------------------------------------*/
- /* I N S E R T */
- /* This routine inserts IDs or IDREFs at the end */
- /* of their appropriate seperate singly linked */
- /* lists. A flag is passed to indicate which */
- /* list the name is to be added to. If the name */
- /* is already present in the list, an error is */
- /* raised. */
- /*------------------------------------------------------*/
- void insert(head,thisname,declvalcode)
- ID_IDREF_DESC **head;
- char thisname[];
- DECLVAL declvalcode;
- {
- ID_IDREF_DESC *thisptr,*prevptr;
-
- thisptr = *head;
- while(thisptr!=NULL && strcmp(thisptr->name,thisname)!=0) {
- prevptr = thisptr;
- thisptr = thisptr->next;
- }
- if (thisptr==NULL && strcmp(prevptr->name,thisname)!=0) {
- if (*head == NULL)
- thisptr = *head = id_idref_alloc();
- else
- thisptr = prevptr->next = id_idref_alloc();
- strcpy(thisptr->name,thisname);
- thisptr->next = NULL;
- }
- else
- if (declvalcode == ID) {
- sprintf(error_msg,"%s%s%s","\nError: Duplicate ID attribute values of '",thisname,"'.\n");
- FATAL_ERROR()
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* L A S T _ S U B L I S T */
- /* This routine is used to find the end of the */
- /* sub-exception list. That is, the list of */
- /* elements declared as an exception for that */
- /* particular generic identifier. */
- /*------------------------------------------------------*/
- EXCEPTDESC *last_sublist(thisglob,thisloc)
- EXCEPTDESC *thisglob,*thisloc;
- {
- if (thisglob==NULL || thisloc==NULL)
- software_fault();
-
- while(thisglob->nextglobal!=thisloc && thisglob->nextglobal!=NULL)
- thisglob = thisglob->nextglobal;
- return(thisglob);
- }
-
- /*------------------------------------------------------*/
- /* L A S T _ G L O B A L */
- /* This routine is used to find the end of the */
- /* entire exception list. That is, the current */
- /* list of elements active as an exception. */
- /*------------------------------------------------------*/
- EXCEPTDESC *last_global(ptr)
- EXCEPTDESC *ptr;
- {
- if (ptr != NULL)
- while(ptr->nextglobal != NULL)
- ptr = ptr->nextglobal;
- return(ptr);
- }
-
- /*------------------------------------------------------*/
- /* L O O K S T A C K */
- /* */
- /* Returns :top value on the stack */
- /* */
- /* Returns the top value of the stack */
- /* but does not pop it off. */
- /*------------------------------------------------------*/
- STENTRY *lookstack()
- {
- STENTRY *ptr;
- if ((ptr=pop()) != NULL) /* pop value */
- push(ptr); /* push it back on the stack */
- return(ptr);
- }
-
- /*------------------------------------------------------*/
- /* N U L L F N C */
- /* This routine doesn't do much of anything. */
- /* It is called by function prototypes to get */
- /* around calling certain routines. For example, */
- /* we don't want to call 'our_fputc' when the */
- /* outdoc is not to be built. */
- /*------------------------------------------------------*/
- nullfnc(value)
- int value;
- {
- return(value);
- }
-
- /*------------------------------------------------------*/
- /* O U R _ F G E T C */
- /* This routine is similiar to K&R's standard */
- /* fgetc. However, It does first read from our */
- /* input stack if something exists on it. */
- /* Otherwise, it does it's own fgetc. */
- /*------------------------------------------------------*/
- our_fgetc(ind)
- FILE *ind;
- {
- register int inchar,retval;
- INPUT_STACK *delptr;
-
- /* We are allowing for future revisions that might require the input
- for the document element parser to come from more than one source. */
-
- if (stptr == NULL) {
- while ((retval=((inchar=fgetc(indoc))==CTRLZ ? EOF:inchar)) == EOF && --fpindx>=0) {
- fclose(fpstack[fpindx+1]);
- indoc = fpstack[fpindx];
- entitylevel--;
- }
- putchar(retval);
- }
- else {
- retval = stptr->inchar;
- delptr = stptr;
- stptr = stptr->next;
- free((char *)delptr);
- }
- return(retval);
- }
-
- /*------------------------------------------------------*/
- /* O U R _ U N G E T C */
- /* This routine is similiar to K&R's standard */
- /* ungetc. However, It creates and uses its */
- /* input stack and places the ungot character */
- /* on it. */
- /*------------------------------------------------------*/
- void our_ungetc(c,indoc)
- int c;
- FILE *indoc;
- {
- INPUT_STACK *newptr;
-
- newptr = isalloc();
- newptr->inchar = c;
- newptr->next = stptr;
- stptr = newptr;
- return;
- }
-
- /*------------------------------------------------------*/
- /* O U R _ T O U P P E R */
- /* We need toupper implemented as a function. */
- /*------------------------------------------------------*/
- our_toupper(value)
- int value;
- {
- if (isascii(value) && isalpha(value) && islower(value))
- return(toupper(value) & 0xFF);
- return(value & 0xFF);
- }
-
- /*------------------------------------------------------*/
- /* P R O C E S S _ A T T R */
- /* This routine is a pre-processor for exe_attr */
- /* that reads from 'indoc' and resolves all */
- /* references, possibly deleting leading and */
- /* trailing spaces, then placing the resulting */
- /* string in 'buffer'. */
- /*------------------------------------------------------*/
- process_attr(buffer,delim,genthead,dvcode,num_csdata)
- char buffer[];
- int delim;
- ENTITYDESC *genthead;
- DECLVAL dvcode;
- unsigned *num_csdata;
- {
- int inchar,indx,charnum,actual_length,inter_length;
- char entname[NAMELEN+1],number[NAMELEN+1];
- ENTITYDESC *entptr;
- BOOLEAN datatext_read;
-
- if (dvcode != ENUM_CDATA)
- actual_length = gettilnosep();
-
- datatext_read = FALSE;
- actual_length = indx = *num_csdata = 0;
-
- while((inchar=our_fgetc(indoc))!=delim || entitylevel>0)
- if (inchar==ERO && !datatext_read)
- if (isalpha(inchar=our_fgetc(indoc))) {
- our_ungetc(inchar,indoc);
- inter_length = get_entname(entname,nullfnc);
- if (entitylevel == 0)
- actual_length += inter_length+1; /* includes the '&' */
-
- if ((entptr=find_entity(genthead,entname,TRUE)) == NULL) {
- sprintf(error_msg,"%s%s%s","\nError: Unknown general entity name '",entname,"'.\n");
- FATAL_ERROR()
- }
- else
- check_entity(dvcode==ENUM_CDATA,num_csdata,entptr,&datatext_read,entname,&actual_length,TRUE,&inchar);
- }
- else
- if (inchar == '#')
- if (isalpha(inchar=our_fgetc(indoc))) {
- our_ungetc(inchar,indoc);
- inter_length = get_entname(entname,our_toupper);
- if (entitylevel == 0)
- actual_length += inter_length+2;
- if (strcmp(entname,"TAB") == 0)
- buffer[indx++] = SEPCHAR;
- else
- if (strcmp(entname,"RS") == 0)
- buffer[indx++] = RS;
- else
- if (strcmp(entname,"RE") == 0)
- buffer[indx++] = RE;
- else
- if (strcmp(entname,"SPACE") == 0)
- buffer[indx++] = SPACE;
- else {
- sprintf(error_msg,"%s%s%s","\nError: Unknown character reference '",entname,"'.\n");
- FATAL_ERROR()
- }
- if ((inchar=our_fgetc(indoc)) != REFC)
- our_ungetc(inchar,indoc);
- else
- actual_length++;
- }
- else
- if (isdigit(inchar)) {
- our_ungetc(inchar,indoc);
- inter_length = get_number(number,nullfnc);
- if (entitylevel == 0)
- actual_length += inter_length+2;
- CLEAR_BUF(); /* don't want number printed out */
-
- charnum = atoi(number);
- if ((charnum<CHARSET_LOWBOUND) || (charnum>CHARSET_HIGHBOUND))
- ourexit(2,"\nError: Invalid character reference number\n");
- else
- buffer[indx++] = charnum;
- if ((inchar=our_fgetc(indoc)) != REFC)
- our_ungetc(inchar,indoc);
- else
- actual_length++;
- }
- else {
- buffer[indx++] = ERO;
- buffer[indx++] = '#';
- buffer[indx++] = inchar;
- }
- else {
- buffer[indx++] = ERO;
- buffer[indx++] = inchar;
- }
- else {
- if (entitylevel == 0)
- actual_length++;
- switch(inchar) {
- case RS:
- break;
- case OUR_EE:
- entitylevel--;
- datatext_read = FALSE;
- break;
- case RE:
- case SEPCHAR:
- buffer[indx++] = SPACE;
- break;
- default:
- buffer[indx++] = inchar;
- break;
- }
- }
- our_ungetc(inchar,indoc);
- if (dvcode != ENUM_CDATA) { /* will strip trailing seps from */
- /* 'buffer' by decrementing 'indx'. */
- while(SEPERATOR(buffer[indx]))
- indx--;
- indx++;
- }
- buffer[indx] = '\0';
- return(actual_length);
- }
-
- /*------------------------------------------------------*/
- /* T R Y _ E N T R E F */
- /* This routine process general entity references, */
- /* named character references, and numeric char- */
- /* acter references if they exist. */
- /*------------------------------------------------------*/
- void try_entref(inchar,genthead,save_char,try_ft)
- int inchar;
- ENTITYDESC *genthead;
- BOOLEAN save_char,*try_ft;
- {
- register int charnum;
- ENTITYDESC *entptr;
- char entname[NAMELEN+1],
- number[NAMELEN+1],
- *outstr;
- static BOOLEAN datatext_read=FALSE;
-
- *try_ft = FALSE;
- outstr = get_char_mem(2);
- number[NAMELEN+1] = '\0';
- if (inchar==ERO && !datatext_read)
- /* Found a general entity reference */
- if (isalpha(inchar=our_fgetc(indoc))) {
- our_ungetc(inchar,indoc);
- get_entname(entname,nullfnc);
- if ((entptr=find_entity(genthead,entname,TRUE)) == NULL) {
- sprintf(error_msg,"%s%s%s","\nError: Unknown general entity name '",entname,"'.\n");
- FATAL_ERROR()
- }
- else
- check_entity(TRUE,(unsigned int *) 0,entptr,&datatext_read,
- entname,(int *) 0,FALSE,&inchar);
- }
- else
- if (inchar == '#')
- /* Found a named character reference */
- if (isalpha(inchar=our_fgetc(indoc))) {
- our_ungetc(inchar,indoc);
- get_entname(entname,our_toupper);
- if (strcmp(entname,"TAB") == 0) {
- (*put_ctr)(SEPCHAR,ctrfp);
- *outstr = SEPCHAR;
- (*applic)(DATA_STG,outstr,"");
- }
- else
- if (strcmp(entname,"RS") == 0) {
- (*put_ctr)(RS,ctrfp);
- *outstr = RS;
- (*applic)(DATA_STG,outstr,"");
- }
- else
- if (strcmp(entname,"RE") == 0) {
- (*put_ctr)(RE,ctrfp);
- *outstr = RE;
- (*applic)(DATA_STG,outstr,"");
- }
- else
- if (strcmp(entname,"SPACE") == 0) {
- (*put_ctr)(SPACE,ctrfp);
- *outstr = SPACE;
- (*applic)(DATA_STG,outstr,"");
- }
- else {
- sprintf(error_msg,"%s%s%s","\nError: Invalid named character reference '",entname,"'.\n");
- FATAL_ERROR()
- }
-
- if ((inchar=our_fgetc(indoc)) != REFC)
- if (inchar == RE) /* RS and RE are insignificant */
- inchar = our_fgetc(indoc); /* get RS */
- else
- our_ungetc(inchar,indoc);
-
- }
- else
- /* Found a numeric character reference */
- if (isdigit(inchar)) {
- our_ungetc(inchar,indoc);
- get_number(number,nullfnc);
- CLEAR_BUF(); /* don't want number printed out */
- charnum = atoi(number);
- if ((charnum<CHARSET_LOWBOUND) || (charnum>CHARSET_HIGHBOUND)) {
- sprintf(error_msg,"%s%s%s","\nError: Invalid numeric character reference '",number,"'.\n");
- FATAL_ERROR()
- }
- else
- if (!SGMLCHAR(charnum)) {
- (*print_ctr)(ctrfp,"\n[#%d]",charnum);
- *try_ft = TRUE;
- }
- else
- (*put_ctr)(charnum,ctrfp);
- *outstr = charnum;
- (*applic)(DATA_STG,outstr,"");
- if ((inchar=our_fgetc(indoc)) != REFC) {
- if (inchar == RE) /* RS and RE are insignificant */
- inchar = our_fgetc(indoc); /* get RS */
- else
- our_ungetc(inchar,indoc);
- }
- }
- else {
- our_ungetc(inchar,indoc);
- (*print_ctr)(ctrfp,"%c#",ERO);
- *outstr = ERO;
- (*applic)(DATA_STG,outstr,"");
- (*applic)(DATA_STG,"#","");
- }
- else {
- our_ungetc(inchar,indoc);
- (*print_ctr)(ctrfp,"%c",ERO);
- *outstr = ERO;
- (*applic)(DATA_STG,outstr,"");
- }
- else
- if (inchar == OUR_EE) {
- datatext_read = FALSE;
- entitylevel--;
- }
- else
- if (save_char)
- our_ungetc(inchar,indoc);
- else
- if (inchar != EOF) {
- (*put_ctr)(inchar,ctrfp);
- *outstr = inchar;
- (*applic)(DATA_STG,outstr,"");
- }
- free(outstr);
- return;
- }
-
- /*------------------------------------------------------*/
- /* R E S O L V E _ A T T R */
- /* This routine resolves the defaults that were */
- /* not explicitly specified in the attribute */
- /* specifications. The defaults are outputted */
- /* to 'outdoc' and IDs and IDREFs are added to */
- /* their appropriate linked lists. */
- /*------------------------------------------------------*/
- resolve_attr(headadp,print_to_file)
- ATTRDESC *headadp;
- int print_to_file;
- {
- char outvalue[LITLEN+1]; /* allow for null terms */
- char buffer[NAMELEN+1];
- register int i,j;
- unsigned num_id_idref;
- BOOLEAN more_def_desc;
- ATTRDESC *thisadp;
-
- num_id_idref = 0;
- for (thisadp=headadp; thisadp!=NULL; thisadp=thisadp->next) {
- if (print_to_file == FALSE)
- putstr_outbuf("\n ");
- else
- (*print_ctr)(ctrfp,"\n ");
- if ((thisadp->defcode==A_IMPLIED||thisadp->defcode==A_CONREF) &&
- thisadp->processed==FALSE) {
- if (print_to_file == FALSE) {
- putchar_outbuf(' ');
- putstr_outbuf(thisadp->attrname);
- putstr_outbuf("=#IMPLIED");
- place_in_queue(TAG_ATTR,thisadp->attrname,"");
- }
- else {
- if (thisadp->dvcode==ID||thisadp->dvcode==IDREF||thisadp->dvcode==IDREFS)
- num_id_idref++;
- (*print_ctr)(ctrfp," %s=#IMPLIED",thisadp->attrname);
- (*applic)(TAG_ATTR,thisadp->attrname,"");
- }
- }
- else {
- if (thisadp->dvcode==GROUP || thisadp->dvcode==NOTATION)
- strcpy(outvalue,thisadp->u2.currgrp->groupname);
- else
- strcpy(outvalue,thisadp->u2.currdef);
- switch(thisadp->defcode) {
- case A_CURRENT: /* if current and IDREF, already in list */
- if (thisadp->dvcode == ID) {
- sprintf(error_msg,"%s%s'.\n","\nError: ID values not unique after default resolution '",thisadp->attrname);
- FATAL_ERROR()
- }
- if (thisadp->dvcode==IDREF || thisadp->dvcode==IDREFS)
- num_id_idref++;
- break;
- case A_UNFIXED:
- case A_FIXED:
- case A_REQD:
- case A_IMPLIED:
- case A_CONREF:
- if (thisadp->dvcode==ID || thisadp->dvcode==IDREF) {
- num_id_idref++;
- #ifdef OLD
- memset(buffer,'\0',NAMELEN+1);
- #else
- memset(buffer,'\0',sizeof(buffer));
- #endif
- for (i=0; i<strlen(outvalue) && i<NAMELEN; i++)
- buffer[i] = outvalue[i];
- #ifdef OLD
- if (i >= NAMELEN)
- ourexit(2,"\nError: ID-IDREF name violates NAMELEN quantity\n");
- #else
- if (strlen(buffer) > NAMELEN)
- ourexit(2,"\nError: ID-IDREF name violates NAMELEN quantity\n");
- #endif
- if (thisadp->dvcode == ID)
- insert(&idhead,buffer,thisadp->dvcode);
- else
- insert(&idrefhead,buffer,thisadp->dvcode);
- }
- else
- if (thisadp->dvcode == IDREFS) {
- more_def_desc = TRUE;
- i = 0;
- while(more_def_desc) {
- num_id_idref++;
- while(thisadp->u2.currdef[i] == ' ')
- i++;
- memset(buffer,'\0',NAMELEN+1);
- j = 0;
- while(!(SEPERATOR(thisadp->u2.currdef[i])) && thisadp->u2.currdef[i]!='\0') {
- buffer[j] = thisadp->u2.currdef[i];
- i++; j++;
- }
- insert(&idrefhead,buffer,thisadp->dvcode);
- more_def_desc = (thisadp->u2.currdef[i] != '\0');
- }
- }
- break;
- }
- if (print_to_file == FALSE) {
- putchar_outbuf(' ');
- putstr_outbuf(thisadp->attrname);
- putstr_outbuf("=\"");
- output_with_lb(strlen(thisadp->attrname)+3,outvalue,FALSE);
- putstr_outbuf("\"");
- place_in_queue(TAG_ATTR,thisadp->attrname,outvalue);
- }
- else {
- if (thisadp->dvcode==ID||thisadp->dvcode==IDREF||thisadp->dvcode==IDREFS)
- num_id_idref++;
- (*print_ctr)(ctrfp," %s=\"",thisadp->attrname);
- output_with_lb(strlen(thisadp->attrname)+3,outvalue,TRUE);
- (*print_ctr)(ctrfp,"\"");
- (*applic)(TAG_ATTR,thisadp->attrname,outvalue);
- }
- }
- }
- return(num_id_idref);
- }
-
- /*--------------------------------------------------------------*/
- /* O U T P U T _ W I T H _ L B */
- /* The CTR requires that output of data or attribute */
- /* values exceeding a column position (nominally 60) */
- /* be broken into multiple lines with a line-break */
- /* character placed at the end of each line. */
- /*--------------------------------------------------------------*/
- void output_with_lb(currcol,outstr,print_to_file)
- int currcol;
- char *outstr;
- BOOLEAN print_to_file;
- {
- char *cptr,buffer[13];
-
- for (cptr=outstr; *cptr != '\0'; cptr++)
- if (++currcol > MAXCOL) {
- if (print_to_file)
- if (SGMLCHAR(*cptr))
- (*print_ctr)(ctrfp,"|\n%c",*cptr);
- else
- (*print_ctr)(ctrfp,"|\n[#%d]",*cptr);
- else {
- if (SGMLCHAR(*cptr)) {
- putstr_outbuf("|\n");
- putchar_outbuf(*cptr);
- }
- else {
- sprintf(buffer,"|\n[#%d]",*cptr);
- putstr_outbuf(buffer);
- }
- }
- currcol = 0;
- }
- else
- if (print_to_file)
- if (SGMLCHAR(*cptr))
- (*print_ctr)(ctrfp,"%c",*cptr);
- else
- (*print_ctr)(ctrfp,"\n[#%d]",*cptr);
- else
- if (SGMLCHAR(*cptr))
- putchar_outbuf(*cptr);
- else {
- sprintf(buffer,"\n[#%d]",*cptr);
- putstr_outbuf(buffer);
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* F I L L U P */
- /* Used to fill up the rest of name, nmtoken, */
- /* or nutoken array. Input is taken from the */
- /* input document and the same restrictions */
- /* apply here in terms of NAMELEN. */
- /*------------------------------------------------------*/
- void fillup(string,indx,capitalize)
- char string[];
- int *indx;
- int (*capitalize)();
- {
- int inchar;
- inchar = our_fgetc(indoc);
- while(NAMECHAR(inchar) && *indx<=NAMELEN) {
- string[*indx] = (*capitalize)(inchar); /* case insensitive */
- putchar_outbuf(string[(*indx)++]);
- inchar = our_fgetc(indoc);
- }
- our_ungetc(inchar,indoc);
- return;
- }
-
- /*------------------------------------------------------*/
- /*------------------------------------------------------*/
- /*------------------------------------------------------*/
- void fillup2(string,indx,capitalize)
- char string[];
- int *indx;
- int (*capitalize)();
- {
- int inchar;
- inchar = our_fgetc(indoc);
- while(NAMECHAR(inchar) && *indx<=NAMELEN) {
- string[*indx] = (*capitalize)(inchar); /* case insensitive */
- (*indx)++;
- inchar = our_fgetc(indoc);
- }
- our_ungetc(inchar,indoc);
- return;
- }
-